home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / newsgrp / group98c.txt / 000153_icon-group-sender _Fri Dec 25 18:21:28 1998.msg < prev    next >
Internet Message Format  |  2000-09-20  |  20KB

  1. Return-Path: <icon-group-sender>
  2. Received: from ursus.CS.Arizona.EDU (ursus.CS.Arizona.EDU [192.12.69.63])
  3.     by baskerville.CS.Arizona.EDU (8.9.1a/8.9.1) with SMTP id SAA20391
  4.     for <icon-group-addresses@baskerville.CS.Arizona.EDU>; Fri, 25 Dec 1998 18:21:27 -0700 (MST)
  5. Received: by ursus.CS.Arizona.EDU (5.65v4.0/1.1.8.2/08Nov94-0446PM)
  6.     id AA01644; Fri, 25 Dec 1998 18:21:26 -0700
  7. Date: Thu, 24 Dec 1998 05:16:02 -0600
  8. Message-Id: <199812241116.FAA01376@segfault.cs.utsa.edu>
  9. From: Clinton Jeffery <jeffery@segfault.cs.utsa.edu>
  10. To: icon-group@optima.CS.Arizona.EDU
  11. Cc: davidr1@express-news.net
  12. Subject: Merry Christmas to all
  13. Reply-To: jeffery@cs.utsa.edu
  14. Errors-To: icon-group-errors@optima.CS.Arizona.EDU
  15. Status: RO
  16.  
  17.  
  18. In the spirit of our own Chris Tenaglia, who has contributed more games to
  19. the Icon community than anyone else, especially on holidays, I would like
  20. to present you with a fine version of the classic game of Tetris.  It was
  21. written by high school senior David Rice, and will be featured in our
  22. forthcoming book, Programming with Icon.  It runs unmodified on UNIX and
  23. Windows Icon, requires graphics facilities, is only a few hundred lines
  24. long, and has a nice feature set.  If you enhance it further, David and
  25. I would love to get copies of your improvements.  I can personally vouch
  26. that it is highly playable, but if you find any bugs or have any problems
  27. with it, we would like to know about that too.  Cheers!
  28.  
  29. Clint Jeffery, jeffery@cs.utsa.edu
  30. Division of Computer Science, The University of Texas at San Antonio
  31. Research http://www.cs.utsa.edu/research/plss.html
  32. Will Hack For Food!
  33.  
  34. ############################################################################
  35. #
  36. #     File:     iTetris.icn
  37. #
  38. #     Subject:  An Icon version of the classic game Tetris
  39. #
  40. #     Author:   David Rice
  41. #
  42. #     Date:     December 10, 1998
  43. #
  44. ############################################################################
  45. #
  46. #   Version:  2.0
  47. #
  48. ############################################################################
  49. #
  50. #   This file is in the public domain.
  51. #
  52. ############################################################################
  53. #
  54. #  This program generates random pieces that fall from the top
  55. #  of the screen.  The object is to position the pieces in a way
  56. #  that they complete a horizontal row.  Scoring is done by 50
  57. #  points for one row, 100 for two, 200 for three, and 400
  58. #  points for a tetris, or four rows.  Another five points are
  59. #  awarded for every piece played.  Levels increase every time
  60. #  that ten rows are deleted.
  61. #
  62. ############################################################################
  63. #
  64. #  Requires:  Version 9 graphics
  65. #
  66. ############################################################################
  67. #
  68. #  Links:  graphics, random
  69. #
  70. ############################################################################
  71.  
  72.  
  73. link graphics
  74. link random
  75.  
  76. $include "keysyms.icn"
  77.  
  78. global activecells, activecellcolor, nextpiece, nextcolor, L,
  79.        colors, score, numrows, level, delaytime, pieceposition,
  80.        button_status, game_status
  81.  
  82.  
  83. procedure main()
  84.    repeat {
  85.       game_status := 0
  86.       init()
  87.       text1 := ["Start", "green", 45, 285]
  88.       text2 := ["Pause", "red", 40, 285]
  89.       button_status := 0
  90.  
  91.       repeat
  92.          if buttons(15, 105, 270, 290, text1, text2) == "done" then break
  93.  
  94.       every cell := !nextpiece do
  95.          drawcell(-40 + (cell[2]-1)*15, 60 + (cell[1]-1)*15,
  96.                   nextcolor)
  97.       every cell := !activecells do
  98.          if cell ~=== colors["black"] then
  99.             drawcell(120 + (cell[2]-1)*15, 481, activecellcolor)
  100.       game_status := 1
  101.       game_loop()
  102.       }
  103. end
  104.  
  105.  
  106. procedure init()
  107.    randomize()
  108.    if /&window then {
  109.       &window := open("iTetris","g","size=276,510", "posx=20",
  110.                        "bg=black")
  111.       }
  112.    WAttrib("fg=white",  "bg=black", "font=sans,bold,15")
  113.    EraseArea(0, 0, 276, 510)
  114.    DrawString(15,50,"Next Object")
  115.    WAttrib("bg=vivid blue", "font=serif,italic,bold,16") 
  116.    GotoXY(4,16)
  117.    WWrites("  ITETRIS 2.0  ")
  118.    WAttrib("fg=dark weak greenish cyan", "linewidth=1", "font=sans,bold,16")
  119.    DrawRectangle(15, 270, 90, 20, 15, 300, 90, 20,
  120.                  15, 330, 90, 20, 15, 360, 90, 20)
  121.    Fg("green")
  122.    DrawString(45, 285, "Start")
  123.    Fg("pale vivid red-yellow")
  124.    DrawString(26, 315, "New Game", 47, 345, "Quit", 41, 375, "About")
  125.    WAttrib("fg=white", "font=serif,italic,bold,16")
  126.    DrawString(12, 150, "Score: " || "0", 12, 170, "Rows: " || "0",
  127.               12, 200, "LEVEL: " || "0")
  128.  
  129.    Fg("dark vivid gray")
  130.    FillRectangle(119,19,152,451, 119,479,152,17)
  131.    WAttrib("fg=pale vivid red-yellow", "bg=dark vivid gray")
  132.    DrawRectangle(119,19,151,451, 119,480,151,16)
  133.  
  134.    numrows := score := level := 0
  135.    delaytime := 200
  136.    colors := table(&window)
  137.    every c := ("blue"|"yellow"|"cyan"|"green"|"red"|"white"|
  138.                "red-yellow" | "purple-magenta") do
  139.       colors[c] := Clone("fg=" || c)
  140.    colors["black"] := Clone(&window, "fg=dark vivid gray")
  141.    L := list(30)
  142.  
  143.    every !L := list(10, colors["black"])
  144.    newobject()
  145.    activecells := copy(nextpiece)
  146.    activecellcolor := copy(nextcolor)
  147.    every point := !activecells do
  148.       L[point[1], point[2]] := colors[activecellcolor]
  149.    newobject()
  150. end
  151.  
  152.  
  153. procedure game_loop()
  154.    repeat {
  155.       while *Pending() > 0 do {
  156.          case Event() of {
  157.             Key_Left  : move_piece(-1, 0)
  158.             Key_Right : move_piece(1, 0)
  159.             Key_Down  : move_piece(0, 1)
  160.             Key_Up    : rotate_piece()
  161.             " "       : drop()
  162.             &lpress   : {
  163.                if 15 <= &x <= 105 then {
  164.                   if 270 <= &y <= 290 then pause()
  165.                      else if 300 <= &y <= 320 then return
  166.                         else if 360 <= &y <= 380 then
  167.                            about_itetris()
  168.                   }
  169.                }
  170.             &lrelease :
  171.                if ((15 <= &x <= 105) & (330 <= &y <= 350)) then
  172.                   exit()
  173.             }
  174.          }
  175.       every point1 := !activecells do {
  176.          if point1[1] + 1 = (point2 := !activecells)[1] &
  177.                            point1[2] = point2[2] then {
  178.             }
  179.          else if (point1[1] = 30) | (L[point1[1] + 1,
  180.                   point1[2]] ~=== colors["black"]) then {
  181.             if point2[1] = 3 then {
  182.                EraseArea(120,481,150,15)
  183.                Bg("black")
  184.                every cell := !nextpiece do
  185.                   EraseArea(-40 + (cell[2]-1)*15,
  186.                             60 + (cell[1]-1)*15, 15, 15)
  187.                every (x := 30 to 1 by -1, y := 1 to 10) do {
  188.                   temp := ?["red-yellow", "yellow", "blue", "cyan",
  189.                             "red", "green", "purple-magenta"]
  190.                   Fg(temp)
  191.  
  192.                   drawcell(120 + (y-1)*15, 20 + (x-1)*15, temp)
  193.                   WDelay(1)
  194.                   }
  195.                every (x := 1 to 30, y := 1 to 10) do {
  196.                   FillRectangle(colors["black"], 120 + (y-1)*15,
  197.                                 20 + (x-1)*15, 15, 15)
  198.                   WDelay(1)
  199.                   }
  200.                Notice("Game Over")
  201.                return
  202.                }
  203.             while get(Pending())
  204.             scanrows()
  205.             Fg("black")            
  206.             DrawString(12, 150, "Score: " || score)
  207.             score +:= 5
  208.             Fg("white")
  209.             DrawString(12, 150, "Score: " || score)
  210.             activecells := copy(nextpiece)
  211.             activecellcolor := copy(nextcolor)
  212.             every point := !activecells do
  213.                L[point[1], point[2]] := colors[activecellcolor]
  214.             newobject()
  215.             EraseArea(120,481,150,15)
  216.             Bg("black")
  217.             every cell := !activecells do {
  218.                EraseArea(-40 + (cell[2]-1)*15, 60 + (cell[1]-1)*15,
  219.                          15, 15)
  220.                if cell ~=== colors["black"] then
  221.           drawcell(120 + (cell[2]-1)*15, 481, activecellcolor)
  222.                }
  223.             every cell := !nextpiece do
  224.            drawcell(-40 + (cell[2]-1)*15,
  225.                       60 + (cell[1]-1)*15, nextcolor)
  226.             break 
  227.             }
  228.          }
  229.  
  230.       newactivecells := []
  231.       Bg("dark vivid gray")
  232.       every cell := !activecells do {
  233.          put(newactivecells, copy(cell))
  234.          newactivecells[-1, 1] +:= 1
  235.          EraseArea(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15,
  236.                         15, 15)
  237.          L[cell[1], cell[2]] := colors["black"]
  238.          }
  239.  
  240.       every cell := !newactivecells do {
  241.          L[cell[1], cell[2]] := colors[activecellcolor]
  242.          drawcell(120 + (cell[2]-1)*15,
  243.                   20 + (cell[1]-1)*15, activecellcolor)
  244.          }
  245.       WSync()
  246.  
  247.       activecells := newactivecells
  248.       delay(delaytime)
  249.       }
  250. end
  251.  
  252.  
  253. procedure newobject()
  254.    case nextcolor := ?["red-yellow", "red", "yellow", "green",
  255.                        "cyan", "blue", "purple-magenta"] of {
  256.    "red-yellow": {
  257.       nextpiece := [ [1,5], [1,6], [2,5], [2,6] ]
  258.       }
  259.    "red": {
  260.       nextpiece := [ [3,6], [1,6], [2,6], [4,6] ]
  261.       pieceposition := 1
  262.       }
  263.    "yellow": {
  264.       nextpiece := [ [2,6],  [1,6], [2,5], [2,7] ]
  265.       }
  266.    "green": {
  267.       nextpiece := [ [2,6], [1,5], [1,6], [2,7] ]
  268.       pieceposition := 1
  269.       }
  270.    "cyan": {
  271.       nextpiece := [ [2,6], [1,6], [1,7], [2,5] ]
  272.       pieceposition := 1
  273.       }
  274.    "blue": {
  275.       nextpiece := [ [2,6], [1,5], [2,5], [2,7] ]
  276.       }
  277.    "purple-magenta": {
  278.       nextpiece := [ [2,6], [1,7], [2,5], [2,7] ]
  279.       }
  280.    }
  281. end
  282.  
  283.  
  284. procedure move_piece(x, y)
  285.    every point := !activecells do {
  286.       # point wants to move to [point[1], point[2] + 1]
  287.       if ((point[2] + x) < 1) | ((point[2] + x) > 10) then fail
  288.       if point[1] + y > 30 then fail
  289.       if L[point[1] + y, point[2] + x] === colors["black"] then
  290.          next
  291.       every point2 := !activecells do
  292.          if (point[1] + y = point2[1]) &
  293.              point[2] + x = point2[2] then break next
  294.  
  295.       if L[point[1] + y, point[2] + x] ~=== colors["black"] then
  296.          fail
  297.       }
  298.  
  299.    newactivecells := []
  300.    every cell := !activecells do {
  301.       put(newactivecells, copy(cell))
  302.       newactivecells[-1, 2] +:= x
  303.       newactivecells[-1, 1] +:= y
  304.       EraseArea(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15, 15 , 15)
  305.       L[cell[1], cell[2]] := colors["black"]
  306.    }
  307.  
  308.    EraseArea(120,481,150,15)
  309.    every cell := !newactivecells do {
  310.       L[cell[1], cell[2]] := colors[activecellcolor]
  311.       drawcell(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15,
  312.                activecellcolor)
  313.       if cell ~=== colors["black"] then
  314.          drawcell(120 + (cell[2]-1)*15, 481, activecellcolor)
  315.       }
  316.    WSync()
  317.    activecells := newactivecells
  318. end
  319.  
  320.  
  321. procedure drop()
  322.    repeat {
  323.       every point1 := !activecells do {
  324.          if point1[1] + 1 = (point2 := !activecells)[1] &
  325.             point1[2] = point2[2] then {
  326.             }
  327.          else if (point1[1] = 30) |
  328.                (L[point1[1] + 1, point1[2]] ~===
  329.                   colors["black"]) then {
  330.             while get(Pending())
  331.             return
  332.             }
  333.         }
  334.  
  335.       newactivecells := []
  336.       every cell := !activecells do {
  337.          put(newactivecells, copy(cell))
  338.          newactivecells[-1, 1] +:= 1
  339.          EraseArea(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15, 15 , 15)
  340.          L[cell[1], cell[2]] := colors["black"]
  341.          }
  342.  
  343.       every cell := !newactivecells do {
  344.      L[cell[1], cell[2]] := colors[activecellcolor]
  345.      drawcell(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15,
  346.                 activecellcolor)
  347.       }
  348.    WSync()
  349.    activecells := newactivecells
  350.    }
  351. end
  352.  
  353.  
  354. procedure rotate_piece()
  355.    if activecellcolor === "red-yellow" then fail
  356.    newactivecells := list()
  357.    centerpoint := copy(activecells[1])
  358.  
  359.    differencelist := list()
  360.    every point := ! activecells do {
  361.       temp := [ centerpoint[1] - point[1],
  362.                 centerpoint[2] - point[2] ]
  363.       put(differencelist, temp)
  364.       next
  365.       }
  366.  
  367.    every cell := !activecells do
  368.       put(newactivecells, copy(cell))
  369.    if activecellcolor === ("red" | "green" | "cyan") &
  370.                           (pieceposition = 2) then {
  371.       every foo := 1 to *newactivecells do {
  372.          newactivecells[foo,1] := centerpoint[1] + differencelist[foo,2]
  373.          newactivecells[foo,2] := centerpoint[2] + differencelist[foo,1] * -1
  374.          pieceposition := 1
  375.          }
  376.       }
  377.    else {
  378.       every foo := 1 to *newactivecells do {
  379.          newactivecells[foo, 1] := centerpoint[1] + differencelist[foo,2] * -1
  380.          newactivecells[foo, 2] := centerpoint[2] + differencelist[foo,1]
  381.          if activecellcolor === ("red" | "green" | "cyan") &
  382.                                 (pieceposition = 1) then
  383.             pieceposition := 2
  384.          }
  385.       }
  386.  
  387.    every foo := 1 to *newactivecells do {
  388.       if not ((1 <= newactivecells[foo, 1] <= 30) &
  389.               (1 <= newactivecells[foo, 2] <= 10)) then fail
  390.       if L[newactivecells[foo, 1], newactivecells[foo, 2]] ===
  391.                                    colors["black"] then next
  392.       every point2 := !activecells do {
  393.          if (newactivecells[foo, 1] = point2[1]) &
  394.              newactivecells[foo, 2] = point2[2]
  395.                 then break next
  396.          }
  397.  
  398.       if L[newactivecells[foo, 1], newactivecells[foo, 2]] ~===
  399.                                    colors["black"] then fail
  400.       }
  401.  
  402.  
  403.    every cell := !activecells do {
  404.       EraseArea(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15, 15 , 15)
  405.       L[cell[1], cell[2]] := colors["black"]
  406.       }
  407.    EraseArea(120,481,150,15)
  408.    every cell := !newactivecells do {
  409.       L[cell[1], cell[2]] := colors[activecellcolor]
  410.       drawcell(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15,
  411.                activecellcolor)
  412.       if cell ~=== colors["black"] then
  413.          drawcell(120 + (cell[2]-1)*15, 481, activecellcolor)
  414.       }
  415.    WSync()
  416.    activecells := newactivecells
  417. end
  418.  
  419.  
  420. procedure scanrows()
  421.    scanned_rows := table()
  422.    rows_to_delete := []
  423.    every point := !activecells do {
  424.       if \scanned_rows[point[1]] then next
  425.       scanned_rows[point[1]] := 1
  426.       every (x := 1 to 10) do {
  427.          if L[point[1], x] === colors["black"] then {
  428.             break next
  429.             }
  430.          else next
  431.          }
  432.       put(rows_to_delete, point[1])
  433.       }
  434.    if *rows_to_delete > 0 then {
  435.       Fg("black")            
  436.       DrawString(12, 150, "Score: " || score, 12, 170, "Rows: " || numrows,
  437.                  12, 200, "LEVEL: " || level)
  438.  
  439.       numrows +:= *rows_to_delete
  440.       level := integer(numrows / 10)
  441.       score +:= 50 * (2 ^ (*rows_to_delete - 1))
  442.       delaytime := 200 - (10 * level)
  443.       
  444.       Fg("white")
  445.       DrawString(12, 150, "Score: " || score, 12, 170, "Rows: " || numrows,
  446.                  12, 200, "LEVEL: " || level)
  447.       deleterows(rows_to_delete)
  448.       }
  449. end
  450.  
  451.  
  452. procedure deleterows(rows_to_delete)
  453.    temp := []
  454.    current_row := 30
  455.    rows_to_delete := sort(rows_to_delete)
  456.    row_set := set()
  457.    every insert(row_set, !rows_to_delete)
  458.    while current_row >= rows_to_delete[1] do {
  459.       push(temp, pull(L))
  460.       current_row -:= 1
  461.       }
  462.    temp_size := *temp
  463.    current_row := 1
  464.    basesize := *L
  465.    while *temp>0 do {
  466.       if member(row_set, basesize + current_row) then {
  467.          push(L, list(10, colors["black"]))
  468.          pop(temp)
  469.          }
  470.       else
  471.          put(L, pop(temp))
  472.       current_row +:= 1
  473.       }
  474.    every (x := 1 to 30, y := 1 to 10) do  {
  475.        FillRectangle(L[x, y], 120 + (y-1)*15, 20 + (x-1)*15, 15, 15)
  476.        if L[x,y] ~=== colors["black"] then 
  477.           DrawRectangle(colors["white"], 120 + (y-1)*15,
  478.                         20 + (x-1) * 15, 14, 14)
  479.        }
  480.    WSync()
  481. end
  482.  
  483.  
  484. procedure pause()
  485.    text1 := ["Start", "green", 45, 285]
  486.    text2 := ["Pause", "red", 40, 285]
  487.    button_status := 0
  488.    game_status := 0
  489.    Bg("black")
  490.    EraseArea(16, 271, 89, 19)
  491.    Font("sans,bold,16")
  492.    Fg("green")
  493.    DrawString(45, 285, "Start")
  494.    FillRectangle(colors["black"], 120,20,150,450, 120,481,150,15)
  495.  
  496.    every cell := !nextpiece do
  497.       EraseArea(-40 + (cell[2]-1)*15, 60 + (cell[1]-1)*15, 15, 15)
  498.  
  499.    repeat {
  500.       Fg("white")
  501.       Font("sans,italic,bold,20")
  502.       CenterString(195, 234, "-PAUSED-")
  503.       if (buttons(15, 105, 270, 290, text1, text2)) == "done" then
  504.          break
  505.       }
  506.    refresh_screen()
  507.    game_status := 1
  508. end
  509.  
  510.  
  511. procedure buttons(x1, x2, y1, y2, text1, text2)
  512.    while *Pending() > 0 do {
  513.       case Event() of {
  514.          &lpress  : {
  515.             if (15 <= &x <= 105) & (330 <= &y <= 350) then exit()
  516.             if x1 <= &x <= x2 then
  517.                if y1 <= &y <= y2 then {
  518.                   Bg(text1[2])
  519.                   EraseArea(x1 + 1, y1 + 1, 89, 19)
  520.                   Font("sans,bold,16")
  521.                   Fg("black")
  522.                   DrawString(text1[3], text1[4], text1[1])
  523.                   button_status := 1
  524.                   }
  525.                else if (360 <= &y <= 380) then about_itetris()
  526.                   else if (300 <= &y <= 320) then main()
  527.                       else button_status := 0
  528.             }
  529.          &ldrag   : {
  530.             if not ((x1 <= &x <= x2) & (y1 <= &y <= y2)) then
  531.                button_status := 0
  532.             }
  533.          &lrelease: {
  534.             if ((x1 <= &x <= x2) & (y1 <= &y <= y2) &
  535.                 (button_status = 1)) then {
  536.                Bg("black")
  537.                EraseArea(x1 - 2, y1 - 2, 95, 25)
  538.                WAttrib("fg=dark weak greenish cyan", "linewidth=1")
  539.                DrawRectangle(x1, y1, 90, 20)
  540.                Font("sans,bold,16")
  541.                Fg(text2[2])
  542.                DrawString(text2[3], text2[4], text2[1])
  543.                Font("serif,italic,bold,16")
  544.                return "done"
  545.                }
  546.             return "keep goin"
  547.             }
  548.          }
  549.       px := WAttrib("pointerx")
  550.       py := WAttrib("pointery")
  551.       if not ((x1 <= &x <= x2) & (y1 <= &y <= y2)) then {
  552.          Bg("black")
  553.          EraseArea(x1 - 2, y1 - 2, 95, 25)
  554.          WAttrib("fg=dark weak greenish cyan", "linewidth=1")
  555.          DrawRectangle(x1, y1, 90, 20)
  556.          WAttrib("font=sans,bold,16", "fg=" || text1[2])
  557.          DrawString(text1[3], text1[4], text1[1])
  558.          } 
  559.       }
  560. end
  561.  
  562.  
  563. procedure about_itetris()
  564.    about := WOpen("label=About iTetris", "size=300,200", "bg=black",
  565.                   "fg=white", "posx=10", "posy=155") | fail
  566.  
  567.    every cell := !nextpiece do
  568.       EraseArea(-40 + (cell[2]-1)*15, 60 + (cell[1]-1)*15, 15, 15)
  569.    FillRectangle(colors["black"], 120,20,150,450,
  570.                                   120,481,150,15)
  571.    CenterString(about, 150, 25, "Written By: David Rice")
  572.    CenterString(about, 150, 50, "Communications Arts HS, San Antonio")
  573.    CenterString(about, 150, 90, "with technical assistance from")
  574.    CenterString(about, 150, 115, "Clinton Jeffery")
  575.    CenterString(about, 150, 180, "Christmas 1998")
  576.  
  577.    repeat {
  578.       case Event(about) of {
  579.          "\e" | "Q" | "q" : break 
  580.          &lpress          : break 
  581.          }
  582.       }
  583.       while get(Pending())
  584.    WClose(about)
  585.    if game_status = 1 then refresh_screen()
  586. end
  587.  
  588.  
  589. procedure refresh_screen()
  590.    Bg("dark vivid gray")
  591.    every cell := !nextpiece do
  592.       drawcell(-40 + (cell[2]-1)*15, 60 + (cell[1]-1)*15,
  593.                nextcolor)
  594.    every cell := !activecells do {
  595.       if cell ~=== colors["black"] then
  596.          drawcell(120 + (cell[2]-1)*15, 481, activecellcolor)
  597.       }
  598.  
  599.    every (x := 1 to 30, y := 1 to 10) do {
  600.       FillRectangle(L[x, y], 120 + (y-1)*15, 20 + (x-1)*15, 15, 15)
  601.       if L[x,y] ~=== colors["black"] then 
  602.          DrawRectangle(colors["white"], 120 + (y-1)*15,
  603.                        20 + (x-1) * 15, 14, 14)
  604.       }
  605. end
  606.  
  607.  
  608. procedure drawcell(x,y,color)
  609.    FillRectangle(colors[color],x,y,15,15)
  610.    DrawRectangle(colors["white"], x, y, 14, 14)
  611. end
  612.